Conversation
ekintel
requested review from
Fridge003,
HaiShaw,
Qiaolin-Yu,
Ying1123,
hebiao064,
hnyls2002,
ispobock and
merrymercy
as code owners
August 28, 2026 04:40
5 tasks
Author
|
Could a maintainer run /tag-and-rerun-ci here please? cc @mingfeima |
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
This PR enables DFlash speculative decoding on Xeon CPUs which currently is rejected outright.
I could not find an existing PR for this. The closest related work is #35629
(NPU DFlash2, open), #27854 (AMD DFlash fused KV, merged) and #30964 (AMD
DSPARK, merged).
Modifications
arg_groups/speculative_hook.pydevice == "cpu"in the DFLASH gate; disable the overlap schedule for CPU spec decode; addintel_amxto the supported draft-attention backends and default to it on CPU.server_args.pyintel_amxtoDRAFT_ATTENTION_BACKEND_CHOICES.speculative/draft_worker_common.py_default_draft_attention_backend()so a CPU run no longer falls back toflashinfer, which failed at the first draft forward. Consumed by DFLASH and DSPARK only; EAGLE is untouched.layers/attention/intel_amx_backend.pyfull_attentionlayers areAttentionType.ENCODER_ONLY, so every query in a block must see every key in it; supply an all-visible per-block mask (cached per(bs, draft_token_num)) in that case.speculative/dflash_info.pyDFlashVerifyInput.tree_topkproperty (returnstopk), so the backend's chain-vs-tree check works uniformly across spec algorithms.speculative/dflash_utils.pyIntelAMXAttnBackendto the verify custom-mask skip list; refuse to slice an AMX-prepackedqkv_projweight; adddflash_head_logits(), which routes throughweight_packed_linear+ column slice on AMX and row slice +matmulotherwise.models/dflash.py,speculative/dflash_worker_v2.pydflash_head_logits(); skip CUDA-graph capture andrecord_streamon CPU; skip the table QK-norm/RoPE fast path on CPU.The reason
dflash_head_logits()is needed: on CPU + AMX,ParallelLMHeadgetsPackWeightMethod, solm_head.weightis VNNI-packed — butshould_apply_lm_head_quant_methodisFalseandis_dense_head_weightisTrue, so the existing dense matmul paths read packed bytes as if they wereplain bf16 and produce garbage.
VocabParallelEmbeddingis not packed, so theembedding path is unaffected.
Two new registered CPU unit tests.
test/registered/unit/spec/test_dflash_cpu.pycovers the device gate, the CPUoverlap-schedule resolution, draft-backend resolution, the linear-chain
tree_topk, and the AMX-prepacked weight guards.test/registered/unit/layers/attention/test_intel_amx_non_causal_mask.pypinsthe new all-visible mask for an
ENCODER_ONLYverify layer and, as a negativecontrol, that a causal layer still takes the mask-free kernel path.
Only
intel_amxis enabled as a CPU draft backend.torch_nativeisdeliberately excluded: it is not validated here, and #36361 proposes rejecting
that backend with speculative decoding outright.
Accuracy Tests
Intel Xeon 6 (128 physical cores across 4 NUMA nodes),
meta-llama/Llama-3.1-8B-Instruct+z-lab/LLaMA3.1-8B-Instruct-DFlash-UltraChat:Single rank
At
temperature: 0the output was byte-identical with and without DFlash.Speculative metrics for that run:
Tensor parallel
Repeated at
--tp 4withSGLANG_CPU_OMP_THREADS_BIND="0-31|32-63|64-95|96-127"(one rank per NUMA node), since CPU CI runs TP > 1. The greedy output matches the
non-speculative run token for token, so the sharded
ParallelLMHeadandqkv_projpaths behave. The one class of exception is characterised below.GSM8K, 200 questions,
--max-new-tokens 128:--parallel 1)--parallel 8)Each delta is 0.005, a single question, in the direction of DFLASH.
Speed Tests and Profiling
HumanEval (first 20 problems), 128 output tokens with EOS ignored, greedy,
--max-concurrency 1, 3 warmup requests,--tp 4,--mem-fraction-static 0.8,--speculative-dflash-block-size 9(8 drafttokens). Both configurations emit exactly 2560 tokens, so length cannot distort
the comparison.
Mean of 3 runs per configuration:
Run-to-run spread is 1.2% on the speculative side and 0.3% on the baseline.
The result decomposes cleanly. A verify step costs
TPOT x accept_length = 12.23 x 3.75 = 45.9 msagainst a 28.56 ms decode step,a ratio of 1.61, so the predicted speedup is
3.75 / 1.61 = 2.33xagainst2.33x measured. End-to-end speed is fully accounted for by acceptance length
and per-step overhead, with no unexplained residual.
Known limitations
The CPU GDN kernels have no target-verify entry points:
causal_conv1d_update_cpuhas no
intermediate_conv_windowargument and assertsx.dim() == 2,fused_sigmoid_gating_delta_rule_update_cpuhas nodisable_state_update/intermediate-state arguments, and
scatter_mamba_states_after_mtp_verifyisTriton-only. This blocks EAGLE and MTP on those models too, not just DFlash,
so I plan to send it as a separate follow-up PR.
--context-length 8192(or
SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN=1) for this checkpoint pair.That is pre-existing and reproduces on CUDA.
Checklist
CI States
Latest PR Test (Base): ❌ Run #33142487182
Latest PR Test (Extra): ❌ Run #33142486930
Latest PR Test (AMD ROCm 7.2): ❌ Run #33142487031